#region Imported Namespaces
using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Web.UI;
using System.Web.UI.Design;
using System.Web.UI.WebControls;
#endregion

namespace PHSRAG.WebControls
{
	#region Class MonthPager
	/// <summary>
	/// The MonthPager assists in navigation of data within controls such as DataGrid grouped by date.
	/// It contains the following: Range of months being displayed and links to navigate to the previous or next months.
	/// The MonthPager does not do much other than to display its state. Its consumers should wire up event handlers to the
	/// appropriate set of events and manage the actual navigation within the relevant data bound control.
	/// </summary>
	/// <remarks>
	/// Pages which have a DataGrid in them that displays data in a monthly breakdown should use the MonthPager control.
	/// Note that more than one MonthPager control may be used and associated with one DataGrid (for exmple,
	/// one on top and another on the bottom of the DataGrid).
	/// </remarks>
	/// <example>
	/// <p>The following example shows how the page would use this control. The registration of the control can be done
	/// simply by dropping the control on the page in design mode.</p>
	/// <p>Note that the <b>FirstMonth</b> and <b>LastMonth</b> properties are typically set at runtime.
	/// The example shows them being set statically for illustration only.</p>
	/// <code>
	/// <![CDATA[
	/// <%@ Register TagPrefix="cc1" Namespace="PHSRAG.WebControls" Assembly="PHSRAG.WebControls" %>
	/// ...
	/// <body>
	/// ...
	/// <cc1:MonthPager id="monthPager" runat="server" FirstMonth="1/31/05" LastMonth="1/31/06" />
	/// ...
	/// </body>
	/// ]]>
	/// </code>
	/// </example>
	[ToolboxData("<{0}:MonthPager runat=server />"), Designer(typeof(MonthPagerDesigner))]
	public class MonthPager : System.Web.UI.WebControls.WebControl, INamingContainer
	{
		#region Constants
		private const string NextCommand = "Next";
		private const string BackCommand = "Back";
		#endregion

		#region Instance Variables
		private Label		firstMonth;
		private Label		lastMonth;
		private LinkButton	next;
		private LinkButton	back;
		#endregion

		#region Properties
		/// <summary>
		/// Get/Set the first month on the current page.
		/// </summary>
		[Bindable(true), Category("Pagination"), Description("Get/Set the first month")]
		public int FirstMonth
		{
			get { EnsureChildControls(); return GetIntegerSafely(firstMonth); }
			set { EnsureChildControls(); firstMonth.Text = value.ToString(); }
		}
		
		/// <summary>
		/// Get/Set the last month on the current page.
		/// </summary>
		[Bindable(true), Category("Pagination"), Description("Get/Set the last month")] 
		public int LastMonth
		{
			get { EnsureChildControls(); return GetIntegerSafely(lastMonth); }
			set { EnsureChildControls(); lastMonth.Text = value.ToString(); }
		}

		/// <summary>
		/// Enable/Disable the next link.
		/// </summary>
		[Bindable(true), Category("Behavior"), Description("Enable/Disable the next link")] 
		public bool EnableNext
		{
			get { EnsureChildControls(); return next.Enabled; }
			set { EnsureChildControls(); next.Enabled = value; }
		}

		/// <summary>
		/// Enable/Disable the back link.
		/// </summary>
		[Bindable(true), Category("Behavior"), Description("Enable/Disable the back link")] 
		public bool EnableBack
		{
			get { EnsureChildControls(); return back.Enabled; }
			set { EnsureChildControls(); back.Enabled = value; }
		}
		#endregion

		#region Events
		/// <summary>
		/// Add/Remove handler for the next click.
		/// </summary>
		[Category("Action"), Description("Raised when next is clicked")]
		public event CommandEventHandler Next
		{
			add		{ Events.AddHandler(NextCommand, value); }
			remove	{ Events.RemoveHandler(NextCommand, value); }
		}

		/// <summary>
		/// Add/Remove handler for the back click.
		/// </summary>
		[Category("Action"), Description("Raised when back is clicked")]
		public event CommandEventHandler Back
		{
			add		{ Events.AddHandler(BackCommand, value); }
			remove	{ Events.RemoveHandler(BackCommand, value); }
		}
		#endregion

		#region Overrides
		/// <summary>
		/// Create all controls that will be on the MonthPager. Notice that the creation is more than just instantiating
		/// the controls. It also involves in generating the underlying HTML so that the controls shows up per the need.
		/// </summary>
		protected override void CreateChildControls()
		{
			CreateControls();
			GenerateControlTree();
		}

		/// <summary>
		/// Invoked when an event is raised by a child control.
		/// </summary>
		/// <param name="source">Reference to the child control that raised the event</param>
		/// <param name="e">Argument associated with the event</param>
		/// <returns>True if the event was handle by this method; false otherwise</returns>
		protected override bool OnBubbleEvent(object source, EventArgs e)
		{
			// Events raised only by link buttons are handled. If an event handler is associated with the button, invoke it.

			bool handled = false;
            CommandEventArgs args = e as CommandEventArgs;
            LinkButton button = source as LinkButton;
			if (args != null && button != null)
			{
				CommandEventHandler handler = (CommandEventHandler)Events[args.CommandName];
				if (handler != null)
				{
					handler(this, new CommandEventArgs(button.CommandName, null));
					handled = true;
				}
			}
			return handled;
		}
		#endregion

		#region Private Methods
		/// <summary>
		/// Create all controls in the MonthPager.
		/// </summary>
		private void CreateControls()
		{
			Controls.Clear();

			firstMonth = new Label();
			lastMonth = new Label();
			
			next = new LinkButton();
			next.CommandName = next.Text = NextCommand;

			back = new LinkButton();
			back.CommandName = back.Text = BackCommand;
		}

		/// <summary>
		/// Setup the control tree to reflect the actual (and exact) layout of the controls within the MonthPager.
		/// </summary>
		private void GenerateControlTree()
		{
			Controls.Add(new LiteralControl(
				"<table width=\"100%\" class=\"Pager\">\n" +
				"\t<tr>\n" +
				"\t\t<td class=\"LeftSection\">\n" +
				"\t\t\t<nobr>Displaying&nbsp;\n"));
			Controls.Add(firstMonth);
			Controls.Add(new LiteralControl("&nbsp;to&nbsp;"));
			Controls.Add(lastMonth);
			Controls.Add(new LiteralControl(
				"</nobr>\n" +
				"</td>\n" +
				"\t\t<td class=\"RightSection\">"));
			Controls.Add(back);
			Controls.Add(new LiteralControl("&nbsp;|&nbsp;"));
			Controls.Add(next);
			Controls.Add(new LiteralControl(
				"</td>\n" +
				"\t</tr>\n" +
				"</table>"));
		}

		/// <summary>
		/// Get the integer value of a label's text.
		/// </summary>
		/// <param name="label">Label to retrieve value from</param>
		/// <returns>Integer value (>= 0) on success, -1 on failure</returns>
		private static int GetIntegerSafely(Label label)
		{
			int result = -1;
			try
			{
				result = Convert.ToInt32(label.Text);
			}
			catch
			{
			}
			return result;
		}
		#endregion

		#region Internal Methods
		/// <summary>
		/// This method is ONLY invoked by the associated designer to show the control contents at design time.
		/// </summary>
		internal void Design()
		{
			EnsureChildControls();
		}
		#endregion
	}
	#endregion

	#region Class MonthPagerDesigner
	/// <summary>
	/// Designer associated with the MonthPager control.
	/// </summary>
	/// <remarks>
	/// This class cannot be used directly.
	/// </remarks>
	public class MonthPagerDesigner : ControlDesigner
	{
		#region Overrides
		/// <summary>
		/// Force the MonthPager control to create its child controls for display at design time.
		/// </summary>
		/// <returns>HTML representation of the Pager control</returns>
		public override string GetDesignTimeHtml()
		{
			((MonthPager)Component).Design();
			return base.GetDesignTimeHtml();
		}
		#endregion
	}
	#endregion
}
